import codecs
import copy
import datetime
import random
import socket
import time
from codecs import encode, decode
import struct

from robot.api import logger

from Lib.constants import AVP_COMMAND_NAME_MAP
from Lib.zcm.dcc.config import dcc_cfg
from Lib.zcm.assistant import FwVariables

# Diameter Header fields
from Lib.zcm.dcc.model import HDRItem

DIAMETER_FLAG_MANDATORY = 0x40
DIAMETER_FLAG_VENDOR = 0x80
DIAMETER_HDR_REQUEST = 0x80
DIAMETER_HDR_ANSWER = 0x00
DIAMETER_HDR_PROXIABLE = 0x40
DIAMETER_HDR_ERROR = 0x20
DIAMETER_HDR_RETRANSMIT = 0x10
# Include common routines for all modules
ERROR = -1

utf8encoder = codecs.getencoder("utf_8")
utf8decoder = codecs.getdecoder("utf_8")


def create_send_msg(request_dict, avp_dict_map, avp_type):
    # 创建dcc发送报文
    # 用户输入的发送请求值
    avps = []
    # avp_dict_map avp_name对应的avpfile中的信息
    for avp_name in request_dict:
        avp_value = request_dict[avp_name]
        # if type(avp_value) == list:
        #     for group_avp_value in avp_value:
        #         avps.append(encodeAvp(avp_name, group_avp_value, avp_dict_map))
        # else:
        #     avps.append(encodeAvp(avp_name, avp_value, avp_dict_map))
        avps += encodeAvp(avp_name, avp_value, avp_dict_map)
    hdrItem = HDRItem()
    command_name = AVP_COMMAND_NAME_MAP.get(avp_type.upper())
    hdrItem.cmd = dictCOMMANDname2code(command_name)
    initializeHops(hdrItem)
    msg = createReq(hdrItem, avps)

    # CCR_avps = ['1234']
    # print("CCR_avps: ", CCR_avps)
    # CCR = HDRItem()
    # CCR.cmd = dictCOMMANDname2code('Credit-Control')
    # initializeHops(CCR)
    # msg = createReq(CCR, CCR_avps)
    return msg


# 创建报文
def create_CER():
    cer_list = dcc_cfg.get_cer_list()
    CER_avps = []
    for one in cer_list:
        CER_avps.append(encodeAVP(one, []))
    CER = HDRItem()
    CER.cmd = dictCOMMANDname2code("Capabilities-Exchange")
    initializeHops(CER)
    msg = createReq(CER, CER_avps)
    return msg


def create_DPR():
    dpr_list = dcc_cfg.get_dpr_list()
    DPR_avps = []
    for one in dpr_list:
        DPR_avps.append(encodeAVP(one, []))
    DPR = HDRItem()
    DPR.cmd = dictCOMMANDname2code("Disconnect-Peer")
    initializeHops(DPR)
    msg = createReq(DPR, DPR_avps)
    return msg


def create_DWA():
    dwa_list = dcc_cfg.get_dwa_list()
    DWA_avps = []
    for one in dwa_list:
        DWA_avps.append(encodeAVP(one, []))
    DWA = HDRItem()
    DWA.cmd = dictCOMMANDname2code("Device-Watchdog")
    initializeHops(DWA)
    msg = createAsr(DWA, DWA_avps)
    return msg


# ----------------------------------------------------------------------
# Main message decoding routine
# Input: diameter message as HEX string
# Result: class H with splitted message (header+message)
# AVPs in message are NOT splitted
def stripHdr(H, msg):
    if len(msg) == 0:
        return ERROR
    (sver, msg) = chop_msg(msg, 2)
    (slen, msg) = chop_msg(msg, 6)
    (sflag, msg) = chop_msg(msg, 2)
    (scode, msg) = chop_msg(msg, 6)
    (sapp, msg) = chop_msg(msg, 8)
    (shbh, msg) = chop_msg(msg, 8)
    (sete, msg) = chop_msg(msg, 8)
    H.ver = ord(decode(sver, "hex"))
    H.flags = ord(decode(sflag, "hex"))
    H.len = struct.unpack("!I", b"\00" + decode(slen, "hex"))[0]
    H.cmd = struct.unpack("!I", b"\00" + decode(scode, "hex"))[0]
    H.appId = struct.unpack("!I", decode(sapp, "hex"))[0]
    H.HopByHop = struct.unpack("!I", decode(shbh, "hex"))[0]
    H.EndToEnd = struct.unpack("!I", decode(sete, "hex"))[0]

    dbg = dictCOMMANDcode2name(H.flags, H.cmd)
    H.msg = msg
    return


def stripHdrSplit(H, msg):
    if len(msg) == 0:
        return ERROR
    (sver, msg) = chop_msg(msg, 2)
    (slen, msg) = chop_msg(msg, 6)
    (sflag, msg) = chop_msg(msg, 2)
    (scode, msg) = chop_msg(msg, 6)
    (sapp, msg) = chop_msg(msg, 8)
    (shbh, msg) = chop_msg(msg, 8)
    (sete, msg) = chop_msg(msg, 8)
    H.ver = ord(sver.decode("hex"))
    H.flags = ord(sflag.decode("hex"))
    H.len = struct.unpack("!I", "\00" + slen.decode("hex"))[0]
    H.cmd = struct.unpack("!I", "\00" + scode.decode("hex"))[0]
    H.appId = struct.unpack("!I", sapp.decode("hex"))[0]
    H.HopByHop = struct.unpack("!I", shbh.decode("hex"))[0]
    H.EndToEnd = struct.unpack("!I", sete.decode("hex"))[0]
    dbg = dictCOMMANDcode2name(H.flags, H.cmd)
    H.msg = msg
    return


# Split AVPs from message
# Input: H.msg as hex string
# Result: list of undecoded AVPs
def splitMsgAVPs(msg):
    ret = []
    while len(msg) != 0:
        # python2.7 slen="00"+msg[10:16]
        slen = b"00" + msg[10:16]
        mlen = struct.unpack("!I", decode(slen, "hex"))[0]
        plen = calc_padding(mlen)
        (avp, msg) = chop_msg(msg, 2 * plen)
        dbg = "Single AVP", "L", mlen, plen, "D", avp
        ret.append(avp)
    return ret


def chop_msg(msg, size):
    return (msg[0:size], msg[size:])


def dictCOMMANDcode2name(flags, code):
    global dict_commands
    cmd = ERROR
    cmd = dcc_cfg.command_dict_map[code]
    if cmd == ERROR:
        return cmd
    if flags & DIAMETER_HDR_REQUEST == DIAMETER_HDR_REQUEST:
        dbg = cmd + " Request"
    else:
        dbg = cmd + " Answer"
    return dbg


def get_len(msg):
    if not msg:
        return 0
    offset_ = 0
    (ver_and_len,) = struct.unpack_from("!I", msg, offset_)
    return ver_and_len & 0x00FFFFFF


def createAsr(H, avps):
    H.flags |= DIAMETER_HDR_ANSWER
    return createRes(H, avps)


def decode_avp(msg, dict_avps_code_map):
    try:
        (scode, msg) = chop_msg(msg, 8)
        (sflag, msg) = chop_msg(msg, 2)
        (slen, msg) = chop_msg(msg, 6)
        mcode = struct.unpack("!I", decode(scode, "hex"))[0]
        mflags = ord(decode(sflag, "hex"))
        data_len = struct.unpack("!I", b"\00" + decode(slen, "hex"))[0]
        mvid = 0
        if mflags & DIAMETER_FLAG_VENDOR:
            (svid, msg) = chop_msg(msg, 8)
            mvid = struct.unpack("!I", decode(svid, "hex"))[0]
            data_len -= 4
        A = avp_code2name(mcode, mvid, dict_avps_code_map)
        ret = ""
        decoded = False
        if A.type in dcc_cfg.asI32:
            ret = decode_Integer32(msg)
            decoded = True
        # add
        if A.type == "Enumerated":
            ret = decode_Integer32(msg)
            decoded = True
        if A.type in dcc_cfg.asI64:
            decoded = True
            ret = decode_Integer64(msg)
        if A.type in dcc_cfg.asU32:
            decoded = True
            ret = decode_Unsigned32(msg)
        if A.type in dcc_cfg.asU64:
            decoded = True
            ret = decode_Unsigned64(msg)
        if A.type in dcc_cfg.asF32:
            decoded = True
            ret = decode_Float32(msg)
        if A.type in dcc_cfg.asF64:
            decoded = True
            ret = decode_Float64(msg)
        if A.type in dcc_cfg.asUTF8:
            decoded = True
            ret = decode_UTF8String(msg, data_len)
        if A.type in dcc_cfg.asIPAddress:
            decoded = True
            ret = decode_Address(msg)
        if A.type in dcc_cfg.asIP:
            decoded = True
            ret = decode_IP(msg)
        if A.type in dcc_cfg.asTime:
            decoded = True
            ret = decode_Time(msg)
        if A.type == "Grouped":
            decoded = True
            ret = decode_grouped(msg, dict_avps_code_map)
        if not decoded:
            # default is OctetString
            ret = decode_OctetString(msg, data_len)
        return (A.name, ret)
    except BaseException as e:
        raise BaseException("avpcode:%s,flags:%s %s" % (mcode, mflags, str(e)))


# Input: single AVP as HEX string
def decodeAVP(msg):
    try:
        (scode, msg) = chop_msg(msg, 8)
        (sflag, msg) = chop_msg(msg, 2)
        (slen, msg) = chop_msg(msg, 6)
        mcode = struct.unpack("!I", decode(scode, "hex"))[0]
        mflags = ord(decode(sflag, "hex"))
        data_len = struct.unpack("!I", b"\00" + decode(slen, "hex"))[0]
        mvid = 0
        if mflags & DIAMETER_FLAG_VENDOR:
            (svid, msg) = chop_msg(msg, 8)
            mvid = struct.unpack("!I", decode(svid, "hex"))[0]
            data_len -= 4
        A = dictAVPcode2name(mcode, mvid)
        ret = ""
        decoded = False
        if A.type in dcc_cfg.asI32:
            ret = decode_Integer32(msg)
            decoded = True
        # add
        if A.type == "Enumerated":
            ret = decode_Integer32(msg)
            decoded = True
        if A.type in dcc_cfg.asI64:
            decoded = True
            ret = decode_Integer64(msg)
        if A.type in dcc_cfg.asU32:
            decoded = True
            ret = decode_Unsigned32(msg)
        if A.type in dcc_cfg.asU64:
            decoded = True
            ret = decode_Unsigned64(msg)
        if A.type in dcc_cfg.asF32:
            decoded = True
            ret = decode_Float32(msg)
        if A.type in dcc_cfg.asF64:
            decoded = True
            ret = decode_Float64(msg)
        if A.type in dcc_cfg.asUTF8:
            decoded = True
            ret = decode_UTF8String(msg, data_len)
        if A.type in dcc_cfg.asIPAddress:
            decoded = True
            ret = decode_Address(msg)
        if A.type in dcc_cfg.asIP:
            decoded = True
            ret = decode_IP(msg)
        if A.type in dcc_cfg.asTime:
            decoded = True
            ret = decode_Time(msg)
        if A.type == "Grouped":
            decoded = True
            ret = decode_Grouped(msg)
        if not decoded:
            # default is OctetString
            ret = decode_OctetString(msg, data_len)
        return (A.name, ret)
    except BaseException as e:
        raise BaseException("avpcode:%s,flags:%s %s" % (mcode, mflags, str(e)))


def decode_Integer32(data):
    ret = struct.unpack("!I", decode(data, "hex"))[0]
    return int(ret)


def decode_Integer64(data):
    ret = struct.unpack("!Q", decode(data, "hex"))[0]
    return int(ret)


def decode_Unsigned32(data):
    ret = struct.unpack("!I", decode(data, "hex"))[0]
    return int(ret)


def decode_Unsigned64(data):
    ret = struct.unpack("!Q", decode(data, "hex"))[0]
    return int(ret)


def decode_Float32(data):
    ret = struct.unpack("!f", decode(data, "hex"))[0]
    return ret


def decode_Float64(data):
    ret = struct.unpack("!d", decode(data, "hex"))[0]
    return ret


def decode_Address(data):
    if len(data) <= 16:
        data = data[4:12]
        ret = inet_ntop(socket.AF_INET, decode(data, "hex"))
    else:
        data = data[4:36]
        ret = inet_ntop(socket.AF_INET6, decode(data, "hex"))
    return ret


def decode_IP(data):
    if len(data) <= 16:
        ret = inet_ntop(socket.AF_INET, decode(data, "hex"))
    else:
        ret = inet_ntop(socket.AF_INET6, decode(data, "hex"))
    return ret


def decode_OctetString(data, dlen):
    fs = "!" + str(dlen - 8) + "s"
    # ret=struct.unpack(fs,data.decode("hex")[0:dlen-8])[0]
    ret = struct.unpack(fs, decode(data, "hex")[0:dlen - 8])[0]
    ret = str(ret, encoding="utf-8")
    return ret


# Hex          Comments
# 0x00..0x7F   Only byte of a 1-byte character encoding
# 0x80..0xBF   Continuation characters (1-3 continuation characters)
# 0xC0..0xDF   First byte of a 2-byte character encoding
# 0xE0..0xEF   First byte of a 3-byte character encoding
# 0xF0..0xF4   First byte of a 4-byte character encoding
# Note:0xF5-0xFF cannot occur
def decode_UTF8String(data, dlen):
    fs = "!" + str(dlen - 8) + "s"
    ret = struct.unpack(fs, decode(data, "hex")[0:dlen - 8])[0]
    utf8 = utf8decoder(ret)
    return utf8[0]


def decode_Grouped(data):
    dbg = "Decoding Grouped:"
    ret = []
    for gmsg in splitMsgAVPs(data):
        ret.append(decodeAVP(gmsg))
    return ret


def decode_grouped(data, dict_avps_code_map):
    ret = []
    for gmsg in splitMsgAVPs(data):
        ret.append(decode_avp(gmsg, dict_avps_code_map))
    return ret


def decode_Time(data):
    seconds_between_1900_and_1970 = ((70 * 365) + 17) * 86400
    ret = struct.unpack("!I", decode(data, "hex"))[0]
    return int(ret) - seconds_between_1900_and_1970


def inet_ntop(address_family, packed_ip):
    # Convert an IP address from binary form into text represenation
    if address_family == socket.AF_INET:
        return socket.inet_ntoa(packed_ip)
    elif address_family == socket.AF_INET6:
        # IPv6 addresses have 128bits (16 bytes)
        if len(packed_ip) != 16:
            logger.error("Illegal syntax for IP address")
        parts = []
        for left in [0, 2, 4, 6, 8, 10, 12, 14]:
            try:
                value = struct.unpack("!H", packed_ip[left:left + 2])[0]
                hexstr = hex(value)[2:]
            except TypeError:
                logger.error("Illegal syntax for IP address")
            parts.append(hexstr.lstrip("0").lower())
        result = ":".join(parts)
        while ":::" in result:
            result = result.replace(":::", "::")
        # Leaving out leading and trailing zeros is only allowed with ::
        if result.endswith(":") and not result.endswith("::"):
            result = result + "0"
        if result.startswith(":") and not result.startswith("::"):
            result = "0" + result
        return result
    else:
        logger.error("Address family not supported yet")


def dictAVPcode2name(avpcode, vendorcode):
    global dict_avps
    vendor = dictVENDORcode2id(vendorcode)
    key = ",".join([str(avpcode), str(vendor)])
    try:
        return dcc_cfg.dict_avps_code_map[key]
    except BaseException as e:
        raise BaseException("avpcode: %d,vendorcode: %d not find in xml" % (avpcode, vendorcode))


def avp_code2name(avpcode, vendorcode, dict_avps_code_map):
    global dict_avps
    vendor = dictVENDORcode2id(vendorcode)
    key = ",".join([str(avpcode), str(vendor)])
    # 优先取avpfile中的值，其次去xml中的，再没有就报错
    if key in dict_avps_code_map:
        return dict_avps_code_map[key]
    if key in dcc_cfg.dict_avps_code_map:
        return dcc_cfg.dict_avps_code_map[key]
    raise BaseException("avpcode: %d,vendorcode: %d not find in avpfile or xml!" % (avpcode, vendorcode))


def dictVENDORcode2id(code):
    global dict_vendors_map
    try:
        return dcc_cfg.dict_vendors_map[code]
    except BaseException as e:
        raise BaseException("vendor code: %d not find in xml" % code)


# ------------------------------------------------------------

# 根据[avp]节点中的vendor-id到[vendor]节点中查找code,并返回code
def dictVENDORid2code(vendor_id):
    try:
        return dcc_cfg.dict_vendors_id_map[vendor_id]
    except BaseException as e:
        logger.error(":".join(["[dictVENDORid2code]", str(e)]))
        raise


def dictCOMMANDname2code(name):
    try:
        return dcc_cfg.command_dict_name_map[name]
    except BaseException as e:
        logger.error(":".join(["[dictCOMMANDname2code]", str(e)]))
        raise


def initializeHops(H):
    try:
        initializeHops.Hop_by_Hop += 1
        initializeHops.End_to_End += 1
    except:
        initializeHops.Hop_by_Hop = int(time.time()) + random.randint(1, 99999) + random.randint(100000,
                                                                                                 99999999) + int(
            FwVariables.get_task_id())
        initializeHops.End_to_End = initializeHops.Hop_by_Hop % 32768 * 32768

    H.HopByHop = initializeHops.Hop_by_Hop
    H.EndToEnd = initializeHops.End_to_End


# 转换时间戳
def strtime2epoch(TimeStr='20160324060125', Format='%Y%m%d%H%M%S'):
    ss = time.strptime(TimeStr, Format)
    return int(time.mktime(ss) + 2208988800)


def calc_padding(msg_len):
    return msg_len + 3 & -4


def inet_pton(address_family, ip_string):
    try:
        if address_family == socket.AF_INET:
            return socket.inet_aton(ip_string)
        if address_family == socket.AF_INET6:
            JOKER = '*'
            while '::' in ip_string:
                ip_string = ip_string.replace('::', ':' + JOKER + ':')
            joker_pos = None
            ipv4_addr = None
            if '.' in ip_string:
                ipv4_addr = ip_string.split(':')[(-1)]
            result = ''
            parts = ip_string.split(':')
            for part in parts:
                if part == JOKER:
                    if joker_pos is None:
                        joker_pos = len(result)
                else:
                    if part == ipv4_addr:
                        result += socket.inet_aton(ipv4_addr)
                    else:
                        result += part.rjust(4, '0').decode('hex')
            if JOKER in ip_string:
                result = result[:joker_pos] + '\x00' * (16 - len(result)) + result[joker_pos:]
            return result
    except BaseException as e:
        logger.error(":".join(["[inet_pton]", str(e)]))
        raise


def pack_address(address):
    try:
        # chen_edit_flag
        address = str(address, encoding="utf8")
        if address.find('.') != ERROR:
            raw = inet_pton(socket.AF_INET, address)
            d = struct.pack('!h4s', 1, raw)
            return d
        if address.find(':') != ERROR:
            raw = inet_pton(socket.AF_INET6, address)
            d = struct.pack('!h16s', 2, raw)
            return d
    except BaseException as e:
        logger.error(":".join(["[pack_address]", str(e)]))
        raise


def encode_finish(A, flags, pktlen, data):
    try:
        ret = data
        if A.vendor != 0:
            ret = '%08X' % int(A.vendor) + ret
            flags |= DIAMETER_FLAG_VENDOR
            pktlen += 4
        ret = '%08X' % int(A.code) + '%02X' % int(flags) + '%06X' % int(pktlen) + ret
        return ret
    except BaseException as e:
        logger.error(":".join(["[encode_finish]", str(e)]))
        raise


def encode_UTF8String(A, flags, data):
    try:
        # utf8data = utf8encoder(data)[0]
        fs = '!' + str(len(data)) + 's'
        if type(data) != bytes:
            data = data.encode('utf-8')
        ret = encode(struct.pack(fs, data), 'hex')
        pktlen = 8 + len(ret) / 2
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_UTF8String]", str(e)]))
        raise


# 转码模块
def encode_Integer32(A, flags, data):
    try:
        ret = encode(struct.pack('!i', int(data)), 'hex')
        pktlen = 12
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Integer32]", str(e)]))
        raise


def encode_Unsigned32(A, flags, data):
    try:
        ret = encode(struct.pack('!I', int(data)), 'hex')
        pktlen = 12
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Unsigned32]", str(e)]))
        raise


def encode_Integer64(A, flags, data):
    try:
        ret = encode(struct.pack('!q', int(data)), 'hex')
        pktlen = 16
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Integer64]", str(e)]))
        raise


def encode_Unsigned64(A, flags, data):
    try:
        ret = encode(struct.pack('!Q', int(data)), 'hex')
        pktlen = 16
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Unsigned64]", str(e)]))
        raise


def encode_Float32(A, flags, data):
    try:
        ret = encode(struct.pack('!f', float(data)), 'hex')
        pktlen = 12
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Float32]", str(e)]))
        raise


def encode_Float64(A, flags, data):
    try:
        ret = encode(struct.pack('!d', float(data)), 'hex')
        pktlen = 16
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Float64]", str(e)]))
        raise


def encode_Address(A, flags, data):
    try:
        ret = encode(pack_address(data), 'hex')
        pktlen = 8 + len(ret) / 2
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Address]", str(e)]))
        raise


def encode_IP(A, flags, data):
    try:
        ret = encode(pack_address(data), 'hex')[4:]
        pktlen = 8 + len(ret) / 2
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_IP]", str(e)]))
        raise


def encode_Time(A, flags, data):
    try:
        ret = encode(struct.pack('!I', int(data)), 'hex')
        pktlen = 12
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_Time]", str(e)]))
        raise


def encode_Enumerated(A, flags, data):
    try:
        # chen_edit_flag
        data = str(data, encoding="utf8")
        if isinstance(data, str):
            for avp in dcc_cfg.dict_avps:
                Name = avp.getAttribute('name')
                if Name == "Content-Disposition":
                    print("111111")
                if Name == A.name:
                    for e in avp.getElementsByTagName('enum'):
                        if data == e.getAttribute('name'):
                            return encode_Integer32(A, flags, int(e.getAttribute('code')))
                    # dbg = (
                    #  'Enum name=', data, 'not found for AVP', A.name)
                    # bailOut(dbg)
        else:
            return encode_Integer32(A, flags, data)
    except BaseException as e:
        logger.error(":".join(["[encode_Enumerated]", str(e)]))
        raise


def encode_Hex(A, flags, data):
    try:
        data = data.replace(' ', '')
        if len(data) % 2 != 0:
            data = data + '0'
        pktlen = 8 + len(data) / 2
        return encode_finish(A, flags, pktlen, data)
    except BaseException as e:
        logger.error(":".join(["[encode_Hex]", str(e)]))
        raise


def encode_OctetString(A, flags, data):
    try:
        # utf8data = utf8encoder(data)[0]
        fs = '!' + str(len(data)) + 's'
        if type(data) != bytes:
            data = data.encode('utf-8')
        ret = encode(struct.pack(fs, data), 'hex')
        pktlen = 8 + len(ret) / 2
        return encode_finish(A, flags, pktlen, str(ret, encoding="utf-8"))
    except BaseException as e:
        logger.error(":".join(["[encode_OctetString]", str(e)]))
        raise


def dictAVPname2code_n(avpname, avpvalue):
    try:
        return dcc_cfg.avp_dict_map[avpname]
    except BaseException as e:
        logger.error(":".join(["[dictAVPname2code_n]", str(e)]))
        raise


def checkMandatory(mandatory):
    try:
        flags = 0
        if mandatory == 'must':
            flags |= DIAMETER_FLAG_MANDATORY
        return flags
    except BaseException as e:
        logger.error(":".join(["[checkMandatory]", str(e)]))
        raise


def do_encode(A, flags, data):
    try:
        if A.type in dcc_cfg.asUTF8:
            return encode_UTF8String(A, flags, data)
        if A.type in dcc_cfg.asI32:
            return encode_Integer32(A, flags, data)
        if A.type in dcc_cfg.asU32:
            return encode_Unsigned32(A, flags, data)
        if A.type in dcc_cfg.asI64:
            return encode_Integer64(A, flags, data)
        if A.type in dcc_cfg.asU64:
            return encode_Unsigned64(A, flags, data)
        if A.type in dcc_cfg.asF32:
            return encode_Float32(A, flags, data)
        if A.type in dcc_cfg.asF64:
            return encode_Float64(A, flags, data)
        if A.type in dcc_cfg.asIPAddress:
            return encode_Address(A, flags, data, )
        if A.type in dcc_cfg.asIP:
            return encode_IP(A, flags, data)
        if A.type in dcc_cfg.asTime:
            return encode_Time(A, flags, data)
        if A.type == 'Enumerated':
            return encode_Enumerated(A, flags, data)
        if A.type == 'Hex':
            return encode_Hex(A, flags, data)
        return encode_OctetString(A, flags, data)
    except BaseException as e:
        logger.error(":".join(["[do_encode]", str(e)]))
        raise


def get_avp_def(AVP_Name, AVP_Value, avp_dict_map):
    if AVP_Name not in avp_dict_map:
        raise Exception("avp_name:{} not in avpfile!".format(AVP_Name))
    A = avp_dict_map[AVP_Name]
    if A.name == '':
        logger.error('AVP with that name not found')
        return ''
    if A.code == 0:
        logger.error('AVP Code not found')
        return ''
    if A.type == '':
        logger.error('AVP type not defined')
        return ''
    if A.vendor < 0:
        logger.error('Vendor ID does not match')
        return ''
    else:
        data = AVP_Value
    flags = checkMandatory(A.mandatory)
    return do_encode(A, flags, data)


def getAVPDef(AVP_Name, AVP_Value):
    try:
        A = dictAVPname2code_n(AVP_Name, AVP_Value)
        if A.name == '':
            logger.error('AVP with that name not found')
            return ''
        if A.code == 0:
            logger.error('AVP Code not found')
            return ''
        if A.type == '':
            logger.error('AVP type not defined')
            return ''
        if A.vendor < 0:
            logger.error('Vendor ID does not match')
            return ''
        else:
            data = AVP_Value
        flags = checkMandatory(A.mandatory)
        return do_encode(A, flags, data)
    except BaseException as e:
        logger.error(":".join(["[getAVPDef]", str(e)]))
        raise


def joinAVPs(avps):
    try:
        data = ""
        for avp in avps:
            while len(avp) / 2 < calc_padding(int(len(avp) / 2)):
                avp = avp + "00"
            data = data + avp
        return data
    except BaseException as e:
        logger.error(":".join(["[joinAVPs]", str(e)]))
        raise


def createReq(H, avps):
    try:
        H.flags |= DIAMETER_HDR_REQUEST
        return createRes(H, avps)
    except BaseException as e:
        logger.error(":".join(["[createReq]", str(e)]))
        raise


def createRes(H, avps):
    try:
        data = joinAVPs(avps)
        H.len = len(data) / 2 + 20
        ret = "01" + "%06X" % int(H.len) + "%02X" % int(H.flags) + "%06X" % int(H.cmd)
        ret = ret + "%08X" % H.appId + "%08X" % H.HopByHop + "%08X" % H.EndToEnd + data
        return ret
    except BaseException as e:
        logger.error(":".join(["[createRes]", str(e)]))
        raise


# def encodeAvp(avp_name, avp_value, avp_dict_map):
#     if type(avp_value) == dict:
#         tmp_msg = ""
#         for child_avp_name in avp_value:
#             msg_with_dict = encodeAvp(child_avp_name, avp_value[child_avp_name], avp_dict_map)
#             # if type(msg_with_dict) == list:
#             #     pass
#             # else:
#             while len(msg_with_dict) / 2 < calc_padding(int(len(msg_with_dict) / 2)):
#                 msg_with_dict = msg_with_dict + '00'
#             tmp_msg = tmp_msg + msg_with_dict
#         msg = get_avp_def(avp_name, decode(tmp_msg, "hex"), avp_dict_map)
#     # elif type(avp_value) == list:
#     #     msg = []
#     #     for avp_obj in avp_value:
#     #         # avp_obj 字典
#     #         # tmp_msg_child = ""
#     #         # for group_child_avp_name in avp_obj:
#     #             # avp_obj[group_child_avp_name] 字典/列表/字符串
#     #         # tmp_msg_child =
#     #         msg.append(encodeAvp(avp_name, avp_obj, avp_dict_map))
#     #             # while len(msg_with_dict) / 2 < calc_padding(int(len(msg_with_dict) / 2)):
#     #             #     msg_with_dict = msg_with_dict + '00'
#     #             # tmp_msg_child = tmp_msg_child + msg_with_dict
#     #         # while len(tmp_msg_child) / 2 < calc_padding(int(len(tmp_msg_child) / 2)):
#     #         #     tmp_msg_child = tmp_msg_child + '00'
#     #         # tmp_msg = tmp_msg + tmp_msg_child
#     #     # msg = get_avp_def(avp_name, decode(tmp_msg, "hex"), avp_dict_map)
#     else:
#         msg = get_avp_def(avp_name, bytes(str(avp_value), encoding="utf8"), avp_dict_map)
#     return msg

def encodeAvp(avp_name, avp_value, avp_dict_map):
    if type(avp_value) == dict:
        tmp_msg = ""
        for child_avp_name in avp_value:
            msg_with_dict = encodeAvp(child_avp_name, avp_value[child_avp_name], avp_dict_map)
            # if type(msg_with_dict) == list:
            #     pass
            # else:
            msg_with_dict = msg_with_dict[0]
            if not msg_with_dict or not msg_with_dict:
                print(avp_name)
            while len(msg_with_dict) / 2 < calc_padding(int(len(msg_with_dict) / 2)):
                msg_with_dict = msg_with_dict + '00'
            tmp_msg = tmp_msg + msg_with_dict
        msg = [get_avp_def(avp_name, decode(tmp_msg, "hex"), avp_dict_map)]
    elif type(avp_value) == list:
        msg = []
        for avp_obj in avp_value:
            msg += encodeAvp(avp_name, avp_obj, avp_dict_map)
    else:
        msg = [get_avp_def(avp_name, bytes(str(avp_value), encoding="utf8"), avp_dict_map)]
    return msg


def encodeAVP(AVP_Name_AVP_Value, fi_list=[]):
    try:
        if type(AVP_Name_AVP_Value[1]).__name__ == 'list':
            p = ""
            for x in AVP_Name_AVP_Value[1]:
                x = encodeAVP(x, fi_list)
                while len(x) / 2 < calc_padding(int(len(x) / 2)):
                    x = x + '00'
                p = p + x
            msg = getAVPDef(AVP_Name_AVP_Value[0], decode(p, "hex"))
        else:
            if "${" in str(AVP_Name_AVP_Value[1]):
                AVP_Name_AVP_Value[1] = str(AVP_Name_AVP_Value[1])
                for one in enumerate(fi_list):
                    AVP_Name_AVP_Value[1] = AVP_Name_AVP_Value[1].replace("${%d}" % one[0], str(one[1]))
            msg = getAVPDef(AVP_Name_AVP_Value[0], bytes(str(AVP_Name_AVP_Value[1]), encoding="utf8"))
            # msg = getAVPDef(AVP_Name_AVP_Value[0], AVP_Name_AVP_Value[1])
        return msg
    except BaseException as e:
        logger.error(":".join(["[encodeAVP]", str(e)]))
        raise


# --------------------------------------------------

def create_CCR_list(dcc_dist=[], fi_list=[]):
    try:
        CCR_avps = []
        for one in dcc_dist:
            CCR_avps.append(encodeAVP(one, fi_list))
        CCR_avps = ['1234']
        print("CCR_avps: ", CCR_avps)
        CCR = HDRItem()
        CCR.cmd = dictCOMMANDname2code('Credit-Control')
        initializeHops(CCR)
        msg = createReq(CCR, CCR_avps)
        return msg
    except BaseException as e:
        logger.error(":".join(["[create_CCR_list]", str(e)]))
        raise


def CreateCdr(acc_nbr, service_type=None):
    try:
        v_random1 = int(random.uniform(1000000000, 2000000000))
        v_random2 = int(random.uniform(1000000000, 2000000000))

        SESSION_ID = str(v_random1) + ";" + str(v_random2)
        START_TIME = datetime.datetime.now()
        BILLING_NBR = acc_nbr
        CdrDemo = copy.deepcopy(dcc_cfg.DccCfg["DccCfg"]["CdrDemo"])

        # 1-PS|2-IN|4-SMS|8-ISMP
        if service_type == "1":
            CdrDemo["DATA"] = CdrDemo["DATA"].replace("SESSION_ID", "gprs001.zte.com.cn;" + SESSION_ID)
            CdrDemo["DATA"] = CdrDemo["DATA"].replace("START_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["DATA"] = CdrDemo["DATA"].replace("END_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["DATA"] = CdrDemo["DATA"].replace("BILLING_NBR", BILLING_NBR)
            return CdrDemo["DATA"]
        elif service_type == "2":
            CdrDemo["MO_VOICE"] = CdrDemo["MO_VOICE"].replace("SESSION_ID", "scp001.telecom.com;" + SESSION_ID)
            CdrDemo["MO_VOICE"] = CdrDemo["MO_VOICE"].replace("START_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["MO_VOICE"] = CdrDemo["MO_VOICE"].replace("END_TIME", (START_TIME + datetime.timedelta(
                seconds=int(CdrDemo["MO_VOICE"].split("|")[8]))).strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["MO_VOICE"] = CdrDemo["MO_VOICE"].replace("BILLING_NBR", BILLING_NBR)
            return CdrDemo["MO_VOICE"]
        elif service_type == "4":
            CdrDemo["SMS"] = CdrDemo["SMS"].replace("SESSION_ID", "p2psms001.telecom.com;" + SESSION_ID)
            CdrDemo["SMS"] = CdrDemo["SMS"].replace("START_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["SMS"] = CdrDemo["SMS"].replace("END_TIME", (START_TIME + datetime.timedelta(
                seconds=int(CdrDemo["SMS"].split("|")[8]))).strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["SMS"] = CdrDemo["SMS"].replace("BILLING_NBR", BILLING_NBR)
            return CdrDemo["SMS"]
        elif service_type == "8":
            CdrDemo["FUNDIAL"] = CdrDemo["FUNDIAL"].replace("SESSION_ID", "crbt.telecom.com;" + SESSION_ID)
            CdrDemo["FUNDIAL"] = CdrDemo["FUNDIAL"].replace("START_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["FUNDIAL"] = CdrDemo["FUNDIAL"].replace("END_TIME", (START_TIME + datetime.timedelta(
                seconds=int(CdrDemo["FUNDIAL"].split("|")[8]))).strftime("%Y-%m-%d %H:%M:%S"))
            CdrDemo["FUNDIAL"] = CdrDemo["FUNDIAL"].replace("BILLING_NBR", BILLING_NBR)
            return CdrDemo["FUNDIAL"]
        else:
            for _x in CdrDemo:
                if _x == "DATA":
                    CdrDemo[_x] = CdrDemo[_x].replace("SESSION_ID", "gprs001.zte.com.cn;" + SESSION_ID)
                    CdrDemo[_x] = CdrDemo[_x].replace("END_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
                elif _x == "MO_VOICE":
                    CdrDemo[_x] = CdrDemo[_x].replace("SESSION_ID", "scp001.telecom.com;" + SESSION_ID)
                elif _x == "SMS":
                    CdrDemo[_x] = CdrDemo[_x].replace("SESSION_ID", "p2psms001.telecom.com;" + SESSION_ID)
                elif _x == "FUNDIAL":
                    CdrDemo[_x] = CdrDemo[_x].replace("SESSION_ID", "crbt.telecom.com;" + SESSION_ID)
                CdrDemo[_x] = CdrDemo[_x].replace("START_TIME", START_TIME.strftime("%Y-%m-%d %H:%M:%S"))
                CdrDemo[_x] = CdrDemo[_x].replace("END_TIME", (START_TIME + datetime.timedelta(
                    seconds=int(CdrDemo[_x].split("|")[8]))).strftime("%Y-%m-%d %H:%M:%S"))
                CdrDemo[_x] = CdrDemo[_x].replace("BILLING_NBR", BILLING_NBR)
                return CdrDemo[_x]
    except BaseException as e:
        logger.error(":".join(["[CreateCdr]", str(e)]))
        raise


def CreateCustomMsg(acc_nbr, cdr):
    try:
        if type(cdr) == str:
            cdr_dict = eval(cdr)
        else:
            cdr_dict = cdr
        v_random1 = int(random.uniform(1000000000, 2000000000))
        v_random2 = int(random.uniform(1000000000, 2000000000))
        START_TIME = datetime.datetime.now()
        if "START_TIME" in cdr_dict.keys():
            START_TIME = datetime.datetime.strptime(cdr_dict['START_TIME'], '%Y-%m-%d %H:%M:%S')
        if cdr_dict["SERVICE_TYPE"] == "DATA":
            defaultVal = {}
            defaultMsg = "DATA|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|CC_TOTAL_OCTETS|SGSN_ADDRESS|LAC_A|CELL_A|RATING_GROUP|IMEI|3GPP_CHARGING_ID|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE"
            defaultVal["SESSION_ID"] = "gprs001.zte.com.cn;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            defaultVal["END_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = ""
            defaultVal["THIRD_NBR"] = ""
            defaultVal["CC_TOTAL_OCTETS"] = "102400"
            defaultVal["SGSN_ADDRESS"] = "91.151.143.233"
            defaultVal["LAC_A"] = "9999"
            defaultVal["CELL_A"] = "9999"
            defaultVal["RATING_GROUP"] = "71"
            defaultVal["IMEI"] = "9999"
            defaultVal["3GPP_CHARGING_ID"] = "88"
            defaultVal["GGSN_ADDRESS"] = "212.72.152.162"
            defaultVal["CALLED_STATION_ID_APN"] = "internet"
            defaultVal["BYTE_DOWN"] = "51200"
            defaultVal["BYTE_UP"] = "51200"
            defaultVal["MCC_MNC"] = "502"
            defaultVal["3GPP_RAT_TYPE"] = "06"
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "MO_VOICE":
            defaultVal = {}
            defaultMsg = "MO_VOICE|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|DURATION|MSC_ID|CALLED_VLR_NUMBER|CALLED_CELL_ID|RATING_GROUP|IMEI|CALLING_VLR_NUMBER|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE|EVENTTYPE-BCSM|CALLING_CELLID_OR_SAI"
            defaultVal["SESSION_ID"] = "scp001.telecom.com;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            if "DURATION" in cdr_dict.keys():
                if cdr_dict["DURATION"] is not None and cdr_dict["DURATION"] != "":
                    print(cdr_dict["DURATION"])
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
                else:
                    cdr_dict["DURATION"] = "180"
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            else:
                defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                    seconds=180)).strftime("%Y-%m-%d %H:%M:%S")
                print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = "60900254233"
            defaultVal["THIRD_NBR"] = ""
            defaultVal["DURATION"] = "180"
            defaultVal["MSC_ID"] = "60557401661"
            defaultVal["CALLED_VLR_NUMBER"] = "60210000"
            defaultVal["CALLED_CELL_ID"] = "60210000"
            defaultVal["RATING_GROUP"] = "0"
            defaultVal["IMEI"] = "9999"
            defaultVal["CALLING_VLR_NUMBER"] = ""
            defaultVal["GGSN_ADDRESS"] = ""
            defaultVal["CALLED_STATION_ID_APN"] = ""
            defaultVal["BYTE_DOWN"] = "0"
            defaultVal["BYTE_UP"] = "0"
            defaultVal["MCC_MNC"] = ""
            defaultVal["3GPP_RAT_TYPE"] = ""
            defaultVal["EVENTTYPE-BCSM"] = "2"
            defaultVal["CALLING_CELLID_OR_SAI"] = "60210000"
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "MT_VOICE":
            defaultVal = {}
            defaultMsg = "MT_VOICE|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|DURATION|MSC_ID|CALLED_VLR_NUMBER|CALLED_CELL_ID|RATING_GROUP|IMEI|CALLING_VLR_NUMBER|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE|EVENTTYPE-BCSM|CALLING_CELLID_OR_SAI"
            defaultVal["SESSION_ID"] = "scp001.telecom.com;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            if "DURATION" in cdr_dict.keys():
                if cdr_dict["DURATION"] is not None and cdr_dict["DURATION"] != "":
                    print(cdr_dict["DURATION"])
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
                else:
                    cdr_dict["DURATION"] = "180"
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            else:
                defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                    seconds=180)).strftime("%Y-%m-%d %H:%M:%S")
                print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = "60900254233"
            defaultVal["THIRD_NBR"] = ""
            defaultVal["DURATION"] = "180"
            defaultVal["MSC_ID"] = "60557401661"
            defaultVal["CALLED_VLR_NUMBER"] = "60210000"
            defaultVal["CALLED_CELL_ID"] = "60210000"
            defaultVal["RATING_GROUP"] = "0"
            defaultVal["IMEI"] = "9999"
            defaultVal["CALLING_VLR_NUMBER"] = ""
            defaultVal["GGSN_ADDRESS"] = ""
            defaultVal["CALLED_STATION_ID_APN"] = ""
            defaultVal["BYTE_DOWN"] = "0"
            defaultVal["BYTE_UP"] = "0"
            defaultVal["MCC_MNC"] = ""
            defaultVal["3GPP_RAT_TYPE"] = ""
            defaultVal["EVENTTYPE-BCSM"] = "2"
            defaultVal["CALLING_CELLID_OR_SAI"] = "60210000"
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "SMS":
            defaultVal = {}
            defaultMsg = "SMS|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|SERVICE_SPECIFIC_UNITS|MSC_ID|LAC_A|CELL_A|RATING_GROUP|IMEI|3GPP_CHARGING_ID|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE|CALLING_VLR_NUMBER|CALLING_CELLID_OR_SAI"
            defaultVal["SESSION_ID"] = "p2psms001.telecom.com;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            if "DURATION" in cdr_dict.keys():
                if cdr_dict["DURATION"] is not None and cdr_dict["DURATION"] != "":
                    print(cdr_dict["DURATION"])
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
                else:
                    cdr_dict["DURATION"] = "1"
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            else:
                defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                    seconds=1)).strftime("%Y-%m-%d %H:%M:%S")
                print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = "995900254233"
            defaultVal["THIRD_NBR"] = ""
            defaultVal["SERVICE_SPECIFIC_UNITS"] = "1"
            defaultVal["MSC_ID"] = "995557401661"
            defaultVal["LAC_A"] = "9999"
            defaultVal["CELL_A"] = "9999"
            defaultVal["RATING_GROUP"] = "-1"
            defaultVal["IMEI"] = "9999"
            defaultVal["3GPP_CHARGING_ID"] = ""
            defaultVal["GGSN_ADDRESS"] = ""
            defaultVal["CALLED_STATION_ID_APN"] = ""
            defaultVal["BYTE_DOWN"] = "0"
            defaultVal["BYTE_UP"] = "0"
            defaultVal["MCC_MNC"] = ""
            defaultVal["3GPP_RAT_TYPE"] = ""
            defaultVal["CALLING_VLR_NUMBER"] = "60210000"
            defaultVal["CALLING_CELLID_OR_SAI"] = "60210000"
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "MMS":
            defaultVal = {}
            defaultMsg = "MMS|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|DURATION|SGSN_ADDRESS|LAC_A|CELL_A|RATING_GROUP|IMEI|3GPP_CHARGING_ID|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE"
            defaultVal["SESSION_ID"] = "ismp.zte.com.cn;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            defaultVal["END_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = ""
            defaultVal["THIRD_NBR"] = ""
            defaultVal["DURATION"] = "102400"
            defaultVal["SGSN_ADDRESS"] = "91.151.143.233"
            defaultVal["LAC_A"] = "9999"
            defaultVal["CELL_A"] = "9999"
            defaultVal["RATING_GROUP"] = "71"
            defaultVal["IMEI"] = "9999"
            defaultVal["3GPP_CHARGING_ID"] = "88"
            defaultVal["GGSN_ADDRESS"] = "212.72.152.162"
            defaultVal["CALLED_STATION_ID_APN"] = "internet"
            defaultVal["BYTE_DOWN"] = "51200"
            defaultVal["BYTE_UP"] = "51200"
            defaultVal["MCC_MNC"] = "502"
            defaultVal["3GPP_RAT_TYPE"] = "06"
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "FUNDIAL":
            defaultVal = {}
            defaultMsg = "FUNDIAL|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|DURATION|MSC_ID|LAC_A|CELL_A|RATING_GROUP|IMEI|3GPP_CHARGING_ID|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE"
            defaultVal["SESSION_ID"] = "crbt.telecom.com;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            if "DURATION" in cdr_dict.keys():
                if cdr_dict["DURATION"] is not None and cdr_dict["DURATION"] != "":
                    print(cdr_dict["DURATION"])
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
                else:
                    cdr_dict["DURATION"] = "1"
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            else:
                defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                    seconds=1)).strftime("%Y-%m-%d %H:%M:%S")
                print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = "70555"
            defaultVal["THIRD_NBR"] = ""
            defaultVal["DURATION"] = "1"
            defaultVal["MSC_ID"] = "995557401661"
            defaultVal["LAC_A"] = "9999"
            defaultVal["CELL_A"] = "9999"
            defaultVal["RATING_GROUP"] = "-1"
            defaultVal["IMEI"] = "9999"
            defaultVal["3GPP_CHARGING_ID"] = ""
            defaultVal["GGSN_ADDRESS"] = ""
            defaultVal["CALLED_STATION_ID_APN"] = ""
            defaultVal["BYTE_DOWN"] = "0"
            defaultVal["BYTE_UP"] = "0"
            defaultVal["MCC_MNC"] = ""
            defaultVal["3GPP_RAT_TYPE"] = ""
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        elif cdr_dict["SERVICE_TYPE"] == "CF_VOICE":
            defaultVal = {}
            defaultMsg = "CF_VOICE|SESSION_ID|START_TIME|END_TIME|BILLING_NBR|BILLING_IMSI|CALLED_NBR|THIRD_NBR|DURATION|MSC_ID|LAC_A|CELL_A|RATING_GROUP|IMEI|CALLING_VLR_NUMBER|GGSN_ADDRESS|CALLED_STATION_ID_APN|BYTE_DOWN|BYTE_UP|MCC_MNC|3GPP_RAT_TYPE"
            defaultVal["SESSION_ID"] = "scp001.telecom.com;".join(["", ";".join([str(v_random1), str(v_random2)])])
            defaultVal["START_TIME"] = START_TIME.strftime("%Y-%m-%d %H:%M:%S")
            if "DURATION" in cdr_dict.keys():
                if cdr_dict["DURATION"] is not None and cdr_dict["DURATION"] != "":
                    print(cdr_dict["DURATION"])
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
                else:
                    cdr_dict["DURATION"] = "180"
                    defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                        seconds=int(cdr_dict["DURATION"]))).strftime("%Y-%m-%d %H:%M:%S")
                    print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            else:
                defaultVal["END_TIME"] = (START_TIME + datetime.timedelta(
                    seconds=180)).strftime("%Y-%m-%d %H:%M:%S")
                print(defaultVal["START_TIME"], defaultVal["END_TIME"])
            defaultVal["BILLING_NBR"] = acc_nbr
            defaultVal["BILLING_IMSI"] = "9999"
            defaultVal["CALLED_NBR"] = "995900254233"
            defaultVal["THIRD_NBR"] = ""
            defaultVal["DURATION"] = "180"
            defaultVal["MSC_ID"] = "995557401661"
            defaultVal["LAC_A"] = "9999"
            defaultVal["CELL_A"] = "9999"
            defaultVal["RATING_GROUP"] = "0"
            defaultVal["IMEI"] = "9999"
            defaultVal["CALLING_VLR_NUMBER"] = ""
            defaultVal["GGSN_ADDRESS"] = ""
            defaultVal["CALLED_STATION_ID_APN"] = ""
            defaultVal["BYTE_DOWN"] = "0"
            defaultVal["BYTE_UP"] = "0"
            defaultVal["MCC_MNC"] = ""
            defaultVal["3GPP_RAT_TYPE"] = ""
            # 先替换用户自定义的字段取值
            for x in cdr_dict:
                defaultMsg = defaultMsg.replace(x.upper(), cdr_dict[x])
            # 再替换系统默认取值
            for x in defaultVal:
                defaultMsg = defaultMsg.replace(x.upper(), defaultVal[x])
        # log.info("[CreateCustomMsg] defaultMsg: ", defaultMsg)
        return defaultMsg
    except BaseException as e:
        logger.error(":".join(["[CreateCustomMsg]", str(e)]))
        raise


def TransforDcc(custom_msg=None):
    result = []
    try:
        DiamterFormatdist = copy.deepcopy(dcc_cfg.DccCfg["DiamterFormat"])
        Transfer1900TimeList = copy.deepcopy(dcc_cfg.DccCfg["DccCfg"]["Transfer1900TimeList"])

        for x in DiamterFormatdist:
            dccfilterattr = int(x)
            DiamterFormat = DiamterFormatdist[x]
            if not Transfer1900TimeList:
                Transfer1900TimeList = {}

            cdr_list = custom_msg.rstrip().split("|")
            if not cdr_list:
                continue
            for one_t in Transfer1900TimeList:
                fmt = Transfer1900TimeList[one_t]
                if fmt == "1970TimeStamp":
                    cdr_list[int(one_t)] = int(cdr_list[int(one_t)]) + 2208988800
                else:
                    cdr_list[int(one_t)] = strtime2epoch(cdr_list[int(one_t)], fmt)
            dccfilterid = cdr_list[dccfilterattr]
            if dccfilterid in DiamterFormat:
                for _d in DiamterFormat[dccfilterid]:
                    _d1 = copy.deepcopy(_d)
                    msg = create_CCR_list(_d1, cdr_list)
                    result.append(msg)
    except BaseException as e:
        logger.error(":".join(["[TransforDcc]", str(e)]))
        raise
    return result


def create_ccr_message(acc_nbr, service_type=None, cdr_attr=None):
    if acc_nbr[0] != '0' and acc_nbr[0:2] != '60':
        acc_nbr = dcc_cfg.prefix + acc_nbr
    if service_type:
        cdr_list = CreateCdr(acc_nbr=acc_nbr, service_type=service_type)
    elif cdr_attr:
        cdr_list = CreateCustomMsg(acc_nbr=acc_nbr, cdr=cdr_attr)
    else:
        cdr_list = CreateCdr(acc_nbr=acc_nbr)

    messages = TransforDcc(cdr_list)
    return messages
